Compilers are programs that translate computer programs written in source languages, such as FORTRAN, Pascal, C, and C++, into equivalent compiled programs consisting of assembly-language instructions or machine-code instructions. During the compilation process, a compiler may first translate a source-language program into intermediate code and then, during later stages of the compilation process, the compiler may optimize the intermediate code to produce the final assembly-language or machine-code version of the source-language program. Although there is a fairly direct sequential correspondence between the source-language program statements and the intermediate code, subsequent optimizations carried out by a compiler during the later stages of compilation may result in deletion of intermediate code instructions, duplication of intermediate code instructions, or significant alteration of the sequential order of the intermediate code instructions. As a result, the instructions of the final assembly-language or machine-code program may not directly correspond to the original source-language program. Because of this lack or direct correspondence, it may be difficult or impossible to select a particular assembly-language or machine-code instruction from the compiled program and relate that instruction back to a particular line or source-language statement in the source-language program.
A common tool used by programmers to analyze the run-time behavior of compiled programs is to generate run-time profile data. This process generates the relative frequencies at which each instruction in the assembly-language or machine-code program is executed during execution of the program. Profile data may be collected over multiple executions of the program using different input data in order to generate frequencies of execution of instructions under a representative average of various run-time conditions. The profile data may be generated by statistically sampling the contents of a program counter that contains an indication of the instruction currently being executed by a computer. Alternatively, profile data may be generated by trapping the computer prior to, or after, execution of each of a number of different instructions and incrementing a counter for the trapped instruction. A more recent profiling technique involves generation of profile data by dynamic translation of compiled programs, according to the teachings of U.S. Pat. No. 5,815,720, "Use of Dynamic Translation to Collect and Exploit Run-Time Information in an optimizing Compilation System." This technique avoids a compilation step to produce instrumented machine-language or assembly-language code. Another recent profiling technique involves the use of special hardware support included in modern processors for run-time branch prediction to generate profile data, as outlined in: "Using Branch Handling Hardware to Support Profile-Driven Optimization," Conte, Patel, and Cox, Proceeding of the 1994 27th Annual International Symposium on Microarchitecture, November 30-December 2 (San Jose, Calif.).
Profile data may be used by certain optimizing compilers to perform optimizations on the profiled source code to produce a more efficient version of the source code. Profile data may also be used by a programmer in order to analyze a program, in which case the profile data may be presented as a histogram, or, when possible, the source-language version of the program may be annotated to indicate the relative frequencies of execution for the various statements within the source-language program. Whether used directly by an optimizing compiler, or used by a programmer for analysis, the profile data collected from compiled program assembly-language or machine-code instructions needs to be correlated with the source-language statements to which the assembly-language or machine-code instructions correspond.
The problem of correlating profile data with a source-language program is difficult when the assembly-language or machine-code version of the program is generated by an optimizing compiler. In this case, as noted above, there is generally no way to correlate particular assembly-language or machine-code instructions to specific statements within the source-language program because of instruction duplication, elimination, or resequencing.
Certain prior profile-based optimization systems require that profile data be gathered using a specially instrumented and unoptimized version of a source-language program. However, this approach may be problematic for a number of reasons. First, profile data may be collected on a machine that includes only the optimized executable program. On such machines, there will be no specially instrumented and unoptimized version of the program for profiling. Also, certain problems and pathological behaviors that occur during execution of an optimized assembly-language or machine-code program may not occur during execution of the unoptimized assembly-language or machine-code version of the program. If the profile data is being used to identify the cause of such pathological behavior, then profile data collected from a specially instrumented unoptimized version of the program is not useful.
A need has therefore been recognized in the area of performance analysis of computer programs for an improved method for collecting profile data during the execution of optimized assembly-language or machine-code programs and relating the collected profile data back to the source-language program from which the optimized assembly-language or machine-code versions of the program are generated. Such a method needs to allow for collection of useful profile data generated from running optimized assembly-language or machine-code programs, and needs to provide way for profile data generated from optimized assembly-language or machine-code programs to be related back to the source-language programs from which the assembly-language or machine-code program is generated.